package com.hyc.www.controller;

import com.hyc.www.exception.DownloadException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;

/**
 * @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
 * @description 负责提供下载功能
 * @date 2019-07-09 21:56
 */
@WebServlet(urlPatterns = "/download")
public class DownLoadServlet extends HttpServlet {

    //用来标示是否继续下载
    boolean isContinue = false;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Long offset = null;

        //浏览器下载版
        String range = req.getHeader("Range");
        if (range == null) {
            offset = new Long(0);
        } else {
            offset = Long.valueOf(range);
        }

        //前端下载版
        String start = req.getParameter("start");
        if ("begin".equalsIgnoreCase(start)) {
            isContinue = true;
            offset = 0L;
        } else if ("continue".equalsIgnoreCase(start)) {
            isContinue = true;
            resp.sendRedirect("index.jsp");
            return;
        } else if ("pause".equalsIgnoreCase(start)) {
            isContinue = false;
            resp.sendRedirect("index.jsp");
            return;
        }

        String filename = req.getParameter("file");
        String path = "C:\\Users\\Misterchaos\\Documents\\Java Develop Workplaces\\IDEA workspace\\resume\\";
        RandomAccessFile raf = new RandomAccessFile(path + filename, "rw");
        if (!isValidOffset(offset, raf)) {
            resp.setStatus(200);
        } else {
            try {
                try {
                    returnFile(resp, filename, offset, raf);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (DownloadException e) {
                //保存到session中
                HttpSession session = req.getSession();
                session.setAttribute("breakpoint", e.getBreakpoint());
                return;
            }
            resp.setStatus(200);

        }
        System.out.println("下载起始点：" + offset);
    }


    /**
     * 用于向客户端提供下载输出流
     *
     * @return 返回断点
     * @name returnFile
     * @notice none
     * @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
     * @date 2019/7/10
     */
    private void returnFile(HttpServletResponse resp, String filename, Long offset, RandomAccessFile raf) throws IOException, InterruptedException {
        OutputStream os = resp.getOutputStream();
        resp.setHeader("content-disposition", "attachment;filename=" + filename);
        resp.addHeader("content-length", String.valueOf(raf.length()));
        raf.seek(offset);
        byte[] bytes = new byte[1000];
        boolean hasMore = true;
        while (hasMore) {
            if (!isContinue) {
                Thread.sleep(3000);
                System.out.println("the user pause the download at "+raf.getFilePointer());
                continue;
            }else {
                hasMore = raf.read(bytes)!=-1;
            }
            try {
                os.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
                //抛出下载中断异常
                DownloadException exception = new DownloadException();
                exception.setBreakpoint(raf.getFilePointer());
                System.out.println("get an breakpoint:" + raf.getFilePointer());
                throw exception;
            }
        }
        os.close();
    }


    /**
     * 用于检查下载断点是否合理
     *
     * @param offset 下载起始点
     * @param raf    被下载的文件
     * @name isValidOffset
     * @notice none
     * @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
     * @date 2019/7/10
     */
    private boolean isValidOffset(Long offset, RandomAccessFile raf) throws IOException {
        return offset >= 0 && offset <= raf.length();
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        return;
    }
}